﻿using Fuse8.ContentManagementFramework.Administration.Controls;
using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.BizFacade;
using Fuse8.ContentManagementFramework.BizFacade.Managers;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Bases;
using Fuse8.DomainFramework.BusinessService;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Telerik.Web.Mvc;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    [CmsAuthorize(UserGroups = PredefinedUserGroups.Developer)]
    public class CmsSiteController : CmsAdminController
    {
        private CmsSiteImportExportManager _siteImportExportManager;

        public CmsSiteImportExportManager SiteImportExportManager
        {
            get
            {
                if (_siteImportExportManager == null)
                {
                    _siteImportExportManager = new CmsSiteImportExportManager();
                }
                return _siteImportExportManager;
            }
        }

        private IEntityBusinessService<CmsDomain, int> _domainService = new BusinessServiceFacade<CmsDomain, int>();
        private readonly CmsUserGroupService _userGroupService = new CmsUserGroupService();

        public virtual ActionResult Index(int? pageSize)
        {
            int currentPageSize = pageSize ?? DefaultPageSize;
            var data = SiteService.FindAll();
            ViewBag.PageSize = currentPageSize;
            ViewBag.Total = data.Count();
            return View(data);
        }

        [GridAction]
        public virtual ActionResult _Index(int? pageSize)
        {
            var data = SiteService.FindAll();

            return View(new GridModel<CmsSite> { Data = data });
        }

        public ActionResult Add()
        {
            return View(new CmsAdminSiteModel
            {
                AssignedUsers = new List<CmsUser>(),
                AllUsers = GetAllUser()
            });
        }

        [HttpPost]
        public ActionResult Add(CmsAdminSiteModel model)
        {
            if (!ModelState.IsValid)
            {
                model.AllUsers = GetAllUser();
                model.AssignedUsers = new List<CmsUser>();
                return View(model);
            }

            var newSite = new CmsSite()
            {
                SiteName = model.SiteName,
                SiteGroupId = model.SiteGroupId
            };
            SiteService.Add(newSite);

            UpdateSiteProperties(model, newSite);

            return RedirectToAction("Index");
        }

        public ActionResult Edit(int id)
        {
            var site = SiteService.FindOne(id);
            var userGroup = _userGroupService.FindAll().FirstOrDefault(x => x.SiteId == id);
            List<CmsUser> assignedUsers = null;

            if (userGroup != null)
            {
                assignedUsers = new CmsUserService().GetForUserGroup(userGroup.Id).ToList();
            }
            var result = new CmsAdminSiteModel
            {
                Id = site.Id,
                SiteName = site.SiteName,
                SiteUrl = site.Domains != null && site.Domains.Any() ? site.Domains.ElementAt(0).Hostname : null,
                SiteGroupId = site.SiteGroupId,
                AssignedUsers = assignedUsers ?? new List<CmsUser>(),
                AllUsers = assignedUsers != null && assignedUsers.Any() ? GetAllUser().Except(assignedUsers) : GetAllUser()
            };

            return View(result);
        }

        [HttpPost]
        public ActionResult Edit(CmsAdminSiteModel model)
        {
            if (!ModelState.IsValid)
            {
                model.AllUsers = GetAllUser();
                model.AssignedUsers = new List<CmsUser>();
                return View(model);
            }

            var site = SiteService.FindOne(model.Id);
            if (site != null)
            {
                var userGroup = _userGroupService.FindAll().FirstOrDefault(x => x.SiteId == site.Id);
                if (userGroup != null)
                {
                    _userGroupService.Remove(userGroup);
                }

                site.SiteName = model.SiteName;
                site.SiteGroupId = model.SiteGroupId;
                SiteService.Save(site);

                var domains = _domainService.FindAll().Where(x => x.SiteId == site.Id);
                if (domains.Any())
                {
                    foreach (var cmsDomain in domains)
                    {
                        _domainService.Remove(cmsDomain);
                    }
                }

                UpdateSiteProperties(model, site);
            }

            return RedirectToAction("Index");
        }

        private IEnumerable<CmsUser> GetAllUser()
        {
            return new CmsUserInformationService().GetAllUserInformationForManagement(1, 100).Select(e => e.LoggedInUser);
        }

        public ActionResult Clone()
        {
            var model = new CmsAdminSiteModel
            {
                IsCloneMode = true,
                AllUsers = GetAllUser(),
                AssignedUsers = new List<CmsUser>()
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult Clone(CmsAdminSiteModel model)
        {
            if (!ModelState.IsValid)
            {
                model.IsCloneMode = true;
                model.AllUsers = GetAllUser();
                model.AssignedUsers = new List<CmsUser>();
                return View(model);
            }

            var newSite = SiteImportExportManager.Clone(new CmsSite(model.SiteToCloneId), model.SiteName);
            UpdateSiteProperties(model, newSite);

            return RedirectToAction("Index");
        }

        public ActionResult Export(int id)
        {
            var site = SiteService.FindOne(id);
            if (site != null)
                return File(SiteImportExportManager.Export(site), "application/x-gzip", site.SiteName);
            return RedirectToAction("Index");
        }

        private void UpdateSiteProperties(CmsAdminSiteModel model, CmsSite newSite)
        {
            // site properties
            var siteProperties = model.ConvertToSiteProperties();
            newSite.SetMetaValue(CmsSite.SitePropertiesKey, siteProperties, true);

            // assign domains
            if (!string.IsNullOrEmpty(siteProperties.SiteUrl))
            {
                var liveDomain = new CmsDomain
                {
                    Hostname = siteProperties.SiteUrl,
                    SiteId = newSite.Id
                };

                TrackingEntityObjectMediator.TrackEntity(liveDomain);
                _domainService.Add(liveDomain);
            }

            // assign users
            var adminGroup = GetOrCreateAdminAccessUserGroup(newSite);

            if (model.SelectedUsers != null)
            {
                foreach (var userId in model.SelectedUsers)
                {
                    UserInformationService.AssignToGroups(userId, new[] { adminGroup });
                }
            }
        }

        private CmsUserGroup GetOrCreateAdminAccessUserGroup(CmsSite site)
        {
            var adminGroup = MembershipService.GetAllUserGroups()
               .SingleOrDefault(userGroup => userGroup.GroupName == PredefinedUserGroups.AdministrationAccess
                               && (userGroup.SiteId == site.Id ||
                                   userGroup.SiteGroupId == site.SiteGroupId && userGroup.SiteId == null ||
                                   userGroup.SiteGroupId == null && userGroup.SiteId == null));

            if (adminGroup == null)
            {
                var originalSite = CmsContext.ContextSite;

                try
                {
                    CmsContext.ContextSite = site;

                    adminGroup = new CmsUserGroup()
                    {
                        GroupName = PredefinedUserGroups.AdministrationAccess,
                        SiteCategory = SiteAwareCategory.Site,
                        IsSystem = true
                    };

                    _userGroupService.Add(adminGroup);
                }
                finally
                {
                    CmsContext.ContextSite = originalSite;
                }
            }

            return adminGroup;
        }
    }
}